const SpecialGroup = require("./SpecialGroup").SpecialGroup
const UploadHuaweiOBS = require("./UploadHuaweiOBS");
const Toolbox = require("../../tool/toolbox")
const path = require("path");
const rs = require("randomstring");

class SpeciaGroupApplication {
  /**
   * 
   * @param {SpecialGroup} sg 
   */
  constructor(sg) {
    this.special_group = sg;
  }


  /**
   * @description 由于程序员的bug,后缀名可以无限长的样子
   * @returns {Promise<{ok:Boolean,msg:String,data:{file_id:Number}}>}
   * @param {String} file_path 
   * @param {Number} parent_id 
   * @param {Number} size_declared 
   * @param {String} defined_name 
   */
  upSingleFile_huaweiFormData(file_path, parent_id = 0, size_declared = 1, defined_name = "") {
    //@todo
    defined_name = defined_name || path.basename(file_path);
    while (true) {
      let parsed = path.parse(defined_name);
      if (parsed.name.length > 100) {
        let part1 = defined_name.substr(0, 100);
        let part2 = defined_name.substr(100);
        part2 = part2.split(".").join("_");
        defined_name = `${part1}.${part2}`
        break;
      }
      if (parsed.name.startsWith(".") && parsed.ext.split(".").join("").length == 0) {
        defined_name = `PADDING${defined_name}`
      }
      break;
    }
    return new Promise(async resolve => {
      let o_token = await this.special_group.requestUploadToken(`${Math.random()}.doc`);
      if (!o_token.ok) {
        return resolve({
          ok: false,
          msg: o_token.msg
        })
      }
      let o_up = await UploadHuaweiOBS.normalFormDataPost(file_path,
        o_token.data.key, o_token.data.policy,
        o_token.data.AccessKeyId, o_token.data.signature,
        o_token.data.upload_domain);
      if (!o_up.ok) {
        return resolve({
          ok: false,
          msg: `UploadHuaweiOBS.normalFormDataPost fail:${o_up.msg}`
        })
      }
      let o_createFile = await this.special_group.createFile_afterUploadObs_100limit(defined_name,
        o_token.data.key, o_up.data.etag, size_declared,
        parent_id);
      if (!o_createFile.ok) {
        return resolve({
          ok: false,
          msg: `this.special_group.createFile_afterUploadObs fail:${o_createFile.msg}`
        })
      }
      return resolve({
        ok: true,
        msg: "ok",
        data: {
          file_id: o_createFile.data.id
        }
      })
    })
  }

  /**
   * 
   * @description 由于程序员的bug,后缀名可以无限长的样子
   * @returns {Promise<{ok:Boolean,msg:String,data:{file_id:Number}}>}
   * @param {String} file_path 
   * @param {Number} parent_id 
   * @param {Number} size_declared 
   * @param {String} defined_name 
   * @param {*} x 
   */
  upSingleFile_huaweiFormData_Xtry(file_path, parent_id = 0, size_declared = 1, defined_name = "", x = 5) {
    return new Promise(async resolve => {
      let errors_log = [];
      for (let i = 1; i <= x; i++) {
        let o_try = await this.upSingleFile_huaweiFormData(file_path, parent_id, size_declared, defined_name);
        if (o_try.ok) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              file_id: o_try.data.file_id
            }
          })
        } else {
          errors_log.push(o_try.msg)
        }
      }
      return resolve({
        ok: false,
        msg: `X=${x} times try fail:${errors_log.join(" , ")}`
      })
    })
  }

  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * id:Number
   * }}>}
   * @param {String} name 
   * @param {Number} parent_id 
   */
  createFolder_NoConflict(name, parent_id = 0) {
    return new Promise(async resolve => {
      let first_try = await this.special_group.createFolder_unlimitedLength(name, parent_id);
      if (first_try.ok) {
        return resolve({
          ok: true,
          msg: "ok",
          data: {
            id: first_try.data.id
          }
        })
      }
      if (first_try.msg == "CONFLICT") {
        let newname = `${name}-${rs.generate(5)}`;
        let o_next = await this.createFolder_NoConflict(newname, parent_id);
        return resolve(o_next)
      } else {
        return resolve({
          ok: false,
          msg: first_try.msg
        })
      }

    })
  }

  /**
   * @returns {Promise<{fatal_fail:Boolean,errors:String[],data:{
   * cloud_dir_id:Number
   * }}>}
   * @param {String} dir_path 
   * @param {Number} parent_id 
   */
  upFolder_huaweiFormData(dir_path, parent_id = 0) {
    return new Promise(async resolve => {
      let o_list = await Toolbox.safeListAllInDir(dir_path);
      let o_root = await this.createFolder_NoConflict(path.basename(dir_path), parent_id);
      // debugger
      if (!o_root.ok) {
        return resolve({
          fatal_fail: true,
          errors: [`不能创建最早的文件夹:${o_root.msg}`]
        })
      }
      const dir2cloudid = {
        "": 0,
        [path.resolve(dir_path)]: o_root.data.id
      }
      /**
       * @returns {Promise<{ok:Boolean,msg:String,data:{cloudid:String}}>}
       * @param {String} child_dir 
       */
      let createDir = (child_dir) => new Promise(async cdresolve => {
        if (dir2cloudid[path.resolve(child_dir)]) {
          return cdresolve({
            ok: true,
            msg: "ok",
            data: {
              cloudid: dir2cloudid[path.resolve(child_dir)]
            }
          })
        }
        let parsed = path.parse(child_dir);
        if (!dir2cloudid[path.resolve(parsed.dir)]) {
          let o_parent = await createDir(parsed.dir);
          if (!o_parent.ok) {
            return cdresolve({
              ok: false,
              msg: o_parent.msg
            })
          }
        }
        let cloud_parent_id = dir2cloudid[path.resolve(parsed.dir)];
        let o_createD = await this.createFolder_NoConflict(parsed.name,
          cloud_parent_id);
        if (!o_createD.ok) {
          return cdresolve({
            ok: false,
            msg: `failed to create dir for:${child_dir}`
          })
        }
        dir2cloudid[path.resolve(child_dir)] = o_createD.data.id;
        return cdresolve({
          ok: true,
          msg: "ok",
          data: { cloudid: o_createD.data.id }
        })
      })
      for (let dir of o_list.filter(e => e.stats.isDirectory()).reverse()) {
        let o_createD = await createDir(dir.full_path);
        if (!o_createD.ok) {
          return resolve({
            fatal_fail: true,
            errors: [`can not create cloud dir for ${dir}::${o_createD.msg}`]
          })
        }
      }
      let file_errrors = [];
      for (let f of o_list.filter(e => e.stats.isFile())) {
        let parent_dir = path.resolve(path.dirname(f.full_path));
        let p_cloud_id = dir2cloudid[parent_dir];
        if (!p_cloud_id) {
          throw {
            msg: "找不到文件对应的父文件夹的云端id",
            file: f.full_path
          }
        }
        let o_up = await this.upSingleFile_huaweiFormData_Xtry(f.full_path, p_cloud_id);
        if (!o_up.ok) {
          file_errrors.push(`upload file fail::${o_up.msg}::${f.full_path}`)
        }
      }
      return resolve({
        fatal_fail: false,
        errors: file_errrors,
        data: {
          cloud_dir_id: o_root.data.id
        }
      })
      debugger
    })
  }


}


module.exports = {
  SpeciaGroupApplication
}